﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Net;

namespace CloudUpload
{
    public partial class Main : Form
    {
        public string   _account = "";
        public string   _container = "";
        public string   _signature = "";
        public bool     _bUseHTTPS = false;

        private Dictionary<string, string> _FilesTargets = null;

        private enum JobTabSelected { None, Upload, Manage };
        private JobTabSelected _ctab = JobTabSelected.None;
          
        public Main()
        {
            _account = Properties.Settings.Default.account;
            _container = Properties.Settings.Default.container;
            _signature = Helper.DecryptString(Properties.Settings.Default.signature);
            _bUseHTTPS = Properties.Settings.Default.usehttps;

            InitializeComponent();

            btUpload.Enabled = false;
        }

        private void btUpload_Click(object sender, EventArgs e)
        {
            btUpload.Enabled = false;
            pbWait.Visible = true;
            _ctab = JobTabSelected.Upload;

            if (_FilesTargets == null)
                return;

            string TargetPath = tbTargetPath.Text;

            if (TargetPath.Length == 0)
            {
                TargetPath = "/";
            }
            else 
            {
                if (!TargetPath.EndsWith("/"))
                    TargetPath += "/";

                if (TargetPath[0] == '/')
                    TargetPath = TargetPath.Substring(1);
            }

            Helper.UploadFiles(
              new AccountInfo { account = _account, container = _container, signature = _signature, usehttps = _bUseHTTPS },
                _FilesTargets, TargetPath, tbStatus, btUpload);
        }

        private void btBrowse_Click(object sender, EventArgs e)
        {
            openFileDialog1.Title = "Choose the file(s) to upload.";
            openFileDialog1.Filter = "All Files|*.*";
            openFileDialog1.FileName = "";
            openFileDialog1.CheckFileExists = true;
            openFileDialog1.CheckPathExists = true;
            openFileDialog1.Multiselect = true;

            DialogResult dr = openFileDialog1.ShowDialog();

            if (dr == DialogResult.OK)
            {
                FillFiles(openFileDialog1.FileNames);
            }
        }

        private void btClear_Click(object sender, EventArgs e)
        {
            tbSourceFile.Text = "";
            tbTargetFileName.Enabled = true;
            tbTargetFileName.Text = "";
            tbTargetPath.Text = "/";
            _FilesTargets = null;
            btUpload.Enabled = false;
        }

        private void tbSourceFile_DragEnter(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop, false) == true)
            {
                e.Effect = DragDropEffects.All;
            } 
        }

        private void FillFiles(string[] files)
        {
            _FilesTargets = null;

            bool bdone = false;
            if (files.Length == 1)
            {
                if (File.Exists(files[0]))
                {
                    _FilesTargets = new Dictionary<string, string>();
                    
                    tbTargetFileName.Enabled = true;
                    tbTargetFileName.Text = Path.GetFileName(files[0]);
                    tbSourceFile.Text = string.Format("'{0}'", tbTargetFileName.Text);
                    _FilesTargets[files[0]] = "";
                   
                    bdone = true;
                }
            }

            if (!bdone)
            {
                _FilesTargets = new Dictionary<string, string>();

                string source = "";

                foreach (var file in files)
                {
                    if (File.Exists(file))
                    {
                        source += string.Format("'{0}' ", Path.GetFileName(file));
                        _FilesTargets[file] = "";
                    }
                    else if (Directory.Exists(file))
                    {
                        string[] listedfiles = Directory.GetFiles(file,"*.*",SearchOption.AllDirectories);

                        string dir = file;
                        int index = dir.LastIndexOf(@"\");
                        dir = dir.Substring(0, index+1);

                        foreach (var f in listedfiles)
                        {
                            source += string.Format("'{0}' ", Path.GetFileName(f));

                            string targetpath = Path.GetDirectoryName(f);
                            targetpath = targetpath.Substring(dir.Length);
                            targetpath = targetpath.Replace(@"\", "/");
                            targetpath += "/";

                            _FilesTargets[f] = targetpath;
                        }

                    }

                }

                tbSourceFile.Text = source;

                if (_FilesTargets.Count > 1)
                {
                    tbTargetFileName.Enabled = false;
                    tbTargetFileName.Text = "<More than one file selected>";
                }
                else
                {
                    tbTargetFileName.Enabled = true;
                    foreach (var kpv in _FilesTargets)
                    {
                        string target = kpv.Value;
                        tbTargetPath.Text = tbTargetPath.Text + target;
                        tbTargetFileName.Text = Path.GetFileName(kpv.Key);
                        break;
                    }
                }
            }
            btUpload.Enabled = true;
        }

        private void tbSourceFile_DragDrop(object sender, DragEventArgs e)
        {
            string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
            FillFiles(files);
        }

        private void btConfig_Click(object sender, EventArgs e)
        {
            Settings dlg = new Settings(_account, _container, _signature, _bUseHTTPS);

            string account,container,signature;
            bool busehttps = false;

            if (dlg.ShowDialog(this,out account,out container,out signature,out busehttps) == DialogResult.OK)
            {
                Properties.Settings.Default.account = account;
                _account = account;

                Properties.Settings.Default.container = container;
                _container = container;

                Properties.Settings.Default.signature = Helper.EncryptString(signature);
                _signature = signature;

                Properties.Settings.Default.usehttps = busehttps;
                _bUseHTTPS = busehttps;

                Properties.Settings.Default.Save();
            }

        }

        private void btRefreshTree_Click(object sender, EventArgs e)
        {
            btRefreshTree.Enabled = false;
            pbWaitManage.Visible = true;

            treeFolder.Nodes.Clear();
            listboxFiles.Items.Clear();

            var treeNode = new TreeNode(_container);
            treeNode.Name = "/";
            treeFolder.Nodes.Add(treeNode);

            PopulateTree("", treeNode);

            pbWaitManage.Visible = false;
            btRefreshTree.Enabled = true;
        }

        protected void PopulateTree(string startingSubDir, TreeNode node)
        {
            IEnumerable<string> DirList = Helper.GetDirList(
                new AccountInfo { account = _account, container = _container, signature = _signature, usehttps = _bUseHTTPS },
                startingSubDir);

            foreach (var blobItem in DirList)
            {
                string name = blobItem.ToString();
                if (name != "/")
                {
                    string nn = name.Substring(0, name.Length - 1);
                    int index = nn.LastIndexOf('/');
                    if (index > 0)
                    {
                        nn = nn.Substring(index+1);
                    }
                    TreeNode treeNode = new TreeNode(nn);
                    treeNode.Name = name;
                    PopulateTree(name, treeNode);
                    node.Nodes.Add(treeNode);

                }
            }
        }

        private void treeFolder_AfterSelect(object sender, TreeViewEventArgs e)
        {
            if (treeFolder.SelectedNode == null)
                return;

            string selection = treeFolder.SelectedNode.Name;
            if (selection == "/")
            {
                selection = "";
            }

            listboxFiles.Items.Clear();

            IEnumerable<string> DirList = Helper.GetFilesList(
                new AccountInfo { account = _account, container = _container, signature = _signature, usehttps = _bUseHTTPS },
                selection);

            foreach (var rec in DirList)
            {
                string name = rec;
                name = name.Substring(name.LastIndexOf('/') + 1);
                listboxFiles.Items.Add(name);
            }
        }

        private void btUpload_EnabledChanged(object sender, EventArgs e)
        {
            if (pbWait.Visible == true && btUpload.Enabled == true)
            {
                _ctab = JobTabSelected.None;
                pbWait.Visible = false;
            }
        }

        private void btnFileDownload_Click(object sender, EventArgs e)
        {
            if (listboxFiles.SelectedItems.Count > 0)
            {
                folderBrowserDialog1.Description = "Choose the target folder for the file(s) to download:";

                if (folderBrowserDialog1.ShowDialog(this) == DialogResult.OK)
                {
                    Dictionary<string, string> selectedFiles = new Dictionary<string, string>();

                    DisableAllManageButtons();
                    pbWaitManage.Visible = true;
                    tbStatus.Text = "Listing files to download...";

                    TreeNode tn = treeFolder.SelectedNode;
                    string folder = (tn.Name == "/") ? "" : tn.Name;

                    foreach (var si in listboxFiles.SelectedItems)
                    {
                        string sourceBlob = string.Format("{0}{1}", folder, si);
                        selectedFiles.Add(sourceBlob, Path.Combine(folderBrowserDialog1.SelectedPath, si.ToString()));
                    }

                    Helper.DownloadFiles(
                        new AccountInfo { account = _account, container = _container, signature = _signature, usehttps = _bUseHTTPS },
                        selectedFiles, tbStatus, btnFileDownload);
                }
            }
        }

        private void btnFileDownload_EnabledChanged(object sender, EventArgs e)
        {
            if (pbWaitManage.Visible == true && btnFileDownload.Enabled == true)
            {
                EnableAllManageButtons();
                pbWaitManage.Visible = false;
            }
        }

        private void btnFileDelete_Click(object sender, EventArgs e)
        {
            int selcount = listboxFiles.SelectedItems.Count;
            if (selcount > 0)
            {
                if (MessageBox.Show(
                    this, string.Format("Are you sure you want to delete {0} file(s)?\r\nThis operation is IRREVERSIBLE and files cannot be undeleted!", selcount),
                    "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == DialogResult.Yes)
                {
                    List<string> file2Delete = new List<string>();

                    DisableAllManageButtons();
                    pbWaitManage.Visible = true;

                    tbStatus.Text = "Listing files to delete...";

                    TreeNode tn = treeFolder.SelectedNode;
                    string folder = (tn.Name == "/") ? "" : tn.Name;

                    foreach (var si in listboxFiles.SelectedItems)
                    {
                        string sourceBlob = string.Format("{0}{1}", folder, si);
                        file2Delete.Add(sourceBlob);
                    }

                    Helper.DeleteFiles(
                        new AccountInfo { account = _account, container = _container, signature = _signature, usehttps = _bUseHTTPS },
                        file2Delete, tbStatus, btnFileDelete);

                }
            }
        }

        private void btnFileDelete_EnabledChanged(object sender, EventArgs e)
        {
            if (pbWaitManage.Visible == true && btnFileDelete.Enabled == true)
            {
                EnableAllManageButtons();
                treeFolder_AfterSelect(null, null);
                pbWaitManage.Visible = false;
            }
        }

        private void ListFilesToDownload(ref Dictionary<string, string> selectedFiles, string DiskPath, string Dir)
        {
            string folder = Dir;

            IEnumerable<string> DirList = Helper.GetFilesList(
            new AccountInfo { account = _account, container = _container, signature = _signature, usehttps = _bUseHTTPS },
            folder);

            foreach (var rec in DirList)
            {
                string name = rec;
                name = name.Substring(name.LastIndexOf('/') + 1);

                string sourceBlob = string.Format("{0}{1}", folder, name);

                string inv = Dir.Replace('/', '\\');
                selectedFiles.Add(sourceBlob, Path.Combine(DiskPath, Path.Combine(inv, name)));
            }

            IEnumerable<string> DirList2 = Helper.GetDirList(
                new AccountInfo { account = _account, container = _container, signature = _signature, usehttps = _bUseHTTPS },
                folder);

            foreach (var blobItem in DirList2)
            {
                string name = blobItem.ToString();

                ListFilesToDownload(ref selectedFiles, DiskPath, name);
            }

        }

        private void btnDirDownload_Click(object sender, EventArgs e)
        {
            TreeNode tn = treeFolder.SelectedNode;

            if (tn != null)
            {
                DialogResult dr = MessageBox.Show(
                    this, string.Format("Do you want to download the folder '{0}' and all its subfolders?\r\nClick on Yes to download the folder '{0}' and all its subfolders.\r\nClick on No to download only the files in the folder '{0}'.\r\nAnd click on Cancel to cancel the operation.", tn.Text),
                    "Files download...", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);

                if (dr != DialogResult.Cancel)
                {
                    folderBrowserDialog1.Description = "Choose the target folder for the file(s) to download:";

                    if (folderBrowserDialog1.ShowDialog(this) == DialogResult.OK)
                    {
                        Dictionary<string, string> selectedFiles = new Dictionary<string, string>();

                        DisableAllManageButtons();
                        pbWaitManage.Visible = true;

                        tbStatus.Text = "Listing files to download...";

                        if (dr == System.Windows.Forms.DialogResult.No)
                        {
                            string folder = (tn.Name == "/") ? "" : tn.Name;

                            IEnumerable<string> DirList = Helper.GetFilesList(
                            new AccountInfo { account = _account, container = _container, signature = _signature, usehttps = _bUseHTTPS },
                            folder);

                            foreach (var rec in DirList)
                            {
                                string name = rec;
                                name = name.Substring(name.LastIndexOf('/') + 1);

                                string sourceBlob = string.Format("{0}{1}", folder, name);
                                selectedFiles.Add(sourceBlob, Path.Combine(folderBrowserDialog1.SelectedPath, Path.Combine(tn.Text, name)));
                            }

                        }
                        else
                        {
                            string folder = (tn.Name == "/") ? "" : tn.Name;
                            ListFilesToDownload(ref selectedFiles, folderBrowserDialog1.SelectedPath, folder);
                        }

                        Helper.DownloadFiles(
                            new AccountInfo { account = _account, container = _container, signature = _signature, usehttps = _bUseHTTPS },
                            selectedFiles, tbStatus, btnDirDownload);

                    }
                    
                }
            }
        }

        private void btnDirDownload_EnabledChanged(object sender, EventArgs e)
        {
            if (pbWaitManage.Visible == true && btnDirDownload.Enabled == true)
            {
                EnableAllManageButtons();
                pbWaitManage.Visible = false;
            }
        }

        private void ListFilesToDelete(ref List<string> selectedFiles, string Dir)
        {
            string folder = Dir;

            IEnumerable<string> DirList = Helper.GetFilesList(
            new AccountInfo { account = _account, container = _container, signature = _signature, usehttps = _bUseHTTPS },
            folder);

            foreach (var rec in DirList)
            {
                string name = rec;
                name = name.Substring(name.LastIndexOf('/') + 1);

                string sourceBlob = string.Format("{0}{1}", folder, name);

                selectedFiles.Add(sourceBlob);
            }

            IEnumerable<string> DirList2 = Helper.GetDirList(
                new AccountInfo { account = _account, container = _container, signature = _signature, usehttps = _bUseHTTPS },
                folder);

            foreach (var blobItem in DirList2)
            {
                string name = blobItem.ToString();

                ListFilesToDelete(ref selectedFiles, name);
            }
        }

        private void btnDirDelete_Click(object sender, EventArgs e)
        {
            TreeNode tn = treeFolder.SelectedNode;

            if (tn != null)
            {
                if (MessageBox.Show(
                    this, string.Format("Are you sure you want to delete the folder '{0}' and all its subfolders?\r\nThis operation is IRREVERSIBLE!", tn.Text),
                    "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == DialogResult.Yes)
                {
                    List<string> file2Delete = new List<string>();

                    DisableAllManageButtons();
                    pbWaitManage.Visible = true;

                    tbStatus.Text = "Listing files to delete...";

                    string folder = (tn.Name == "/") ? "" : tn.Name;

                    ListFilesToDelete(ref file2Delete, folder);

                    Helper.DeleteFiles(
                        new AccountInfo { account = _account, container = _container, signature = _signature, usehttps = _bUseHTTPS },
                        file2Delete, tbStatus, btnDirDelete);

                }
            }
        }

        private void btnDirDelete_EnabledChanged(object sender, EventArgs e)
        {
            if (pbWaitManage.Visible == true && btnDirDelete.Enabled == true)
            {
                EnableAllManageButtons();
                btRefreshTree_Click(null, null);
                pbWaitManage.Visible = false;
            }
        }

        private void DisableAllManageButtons()
        {
            btnDirDelete.Enabled = false;
            btnDirDownload.Enabled = false;
            btnFileDelete.Enabled = false;
            btnFileDownload.Enabled = false;
            btRefreshTree.Enabled = false;
            _ctab = JobTabSelected.Manage;
        }

        private void EnableAllManageButtons()
        {
            btnDirDelete.Enabled = true;
            btnDirDownload.Enabled = true;
            btnFileDelete.Enabled = true;
            btnFileDownload.Enabled = true;
            btRefreshTree.Enabled = true;
            _ctab = JobTabSelected.None;
        }

        private void tabMain_Selecting(object sender, TabControlCancelEventArgs e)
        {
            if (_ctab != JobTabSelected.None)
            {
                e.Cancel = true;
            }
        }
    }
}
